package com.ccp.dev.workflow.controller;
import com.ccp.dev.core.basic.annotion.Action;
import com.ccp.dev.core.basic.annotion.ActionExecOrder;
import com.ccp.dev.core.basic.consts.UrlConstants;
import com.ccp.dev.core.basic.internationalization.SysBaseController;
import com.ccp.dev.core.basic.model.SysAuditModelType;
import com.ccp.dev.core.basic.response.ResultData;
import com.ccp.dev.core.basic.util.ContextUtil;
import com.ccp.dev.core.basic.web.query.QueryFilter;
import com.ccp.dev.core.util.BeanUtils;
import com.ccp.dev.core.util.RequestUtil;
import com.ccp.dev.form.model.BpmField;
import com.ccp.dev.form.model.FormDef;
import com.ccp.dev.form.model.FormField;
import com.ccp.dev.form.service.FormDefService;
import com.ccp.dev.form.service.FormFieldService;
import com.ccp.dev.system.model.SysRole;
import com.ccp.dev.system.util.SysRoleUtil;
import com.ccp.dev.workflow.model.ActDefModel;
import com.ccp.dev.workflow.model.BpmNodeSet;
import com.ccp.dev.workflow.model.bpm.BpmBatchApproval;
import com.ccp.dev.workflow.model.bpm.BpmTree;
import com.ccp.dev.workflow.model.bpm.ProcessTask;
import com.ccp.dev.workflow.service.ActDefModelService;
import com.ccp.dev.workflow.service.BpmNodeSetService;
import com.ccp.dev.workflow.service.BpmService;
import com.ccp.dev.workflow.service.ProcessRunService;
import com.ccp.dev.workflow.service.bpm.BpmBatchApprovalService;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.collections.map.CaseInsensitiveMap;
import org.apache.commons.text.StringEscapeUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * ClassDescribe:
 * 对象功能:流程批量审批定义设置 控制器类
 *
 * @author :wangcheng
 * Date: 2019-10-08
 */
@Controller
@RequestMapping(UrlConstants.PROJECT_ROOT + UrlConstants.PROJECT_MODULE_WORKFLOW + "/bpmBatchApproval")
@Action(ownermodel = SysAuditModelType.PROCESS_MANAGEMENT)
public class BpmBatchApprovalController extends SysBaseController {
    @Resource
    private BpmBatchApprovalService bpmBatchApprovalService;
    @Resource
    private ActDefModelService actDefModelService;
    @Resource
    private BpmNodeSetService bpmNodeSetService;
    @Resource
    private FormDefService formDefService;
    @Resource
    private FormFieldService formFieldService;
    @Resource
    private ProcessRunService processRunService;
    @Resource
    private BpmService bpmService;

    /**
     * 跳转批量审批设置列表页面
     * @return 批量审批设置列表页面
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + UrlConstants.MODULE_FUNCTION_LIST)
    @Action(description = "跳转流程批量审批定义设置分页列表页面",detail = "跳转流程批量审批定义设置分页列表页面")
    public String viewList(){
        return getAutoView();
    }

    /**
     * 跳转至明细页面
     * @param request http请求
     * @param model 前台model容器
     * @return 批量审批设置定义明细页面
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX+UrlConstants.MODULE_FUNCTION_GET)
    @Action(description = "跳转批量审批设置定义明细页面", detail = "跳转批量审批设置定义明细页面")
    public String viewGet (HttpServletRequest request,Model model){
        String id = RequestUtil.getString(request,"id");
        model.addAttribute("id",id);
        return getAutoView();
    }

    /**
     * 跳转流程审批定义设置编辑页面
     * @param request http请求
     * @param model mvc对象
     * @return 批量审批定义设置编辑页面
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/edit")
    @Action(description = "跳转流程审批定义设置编辑页面", detail = "跳转流程审批定义设置编辑页面")
    public String viewEdit(HttpServletRequest request, Model model) {
        String id = RequestUtil.getString(request, "id");
        BpmBatchApproval batchApproval = bpmBatchApprovalService.getOneById(id);
        if (BeanUtils.isNotEmpty(batchApproval)) {
            model.addAttribute("bpmBatchApproval", batchApproval);
        }
        return getAutoView();
    }

    /**
     * 添加或更新流程批量审批定义设置
     * @param bpmBatchApproval 批量审批定义对象
     * @return 结果统一对象
     */
    @RequestMapping("/save")
    @ResponseBody
    @Action(description = "添加或更新流程批量审批定义设置", detail = "添加或更新流程批量审批定义设置")
    public ResultData save(BpmBatchApproval bpmBatchApproval) {
        bpmBatchApproval.setFieldJson(StringEscapeUtils.unescapeHtml4(bpmBatchApproval.getFieldJson()));
        try {
            boolean isExists = bpmBatchApprovalService.isExists(bpmBatchApproval);
            if (isExists) {
                return getResultDataError("bpmBatchApproval.isExist");
            }
            boolean idAddOrUpdate = bpmBatchApprovalService.save(bpmBatchApproval);
            return getResultDataSuccess(idAddOrUpdate?"bpmBatchApproval.add.success":"bpmBatchApproval.update.success");
        } catch (Exception e) {
            e.printStackTrace();
            return getResultDataError("operation.failure");
        }
    }

    /**
     * 批量审批列表页面
     * @param request http请求
     * @return 审批定义设置列表
     */
    @RequestMapping(UrlConstants.MODULE_FUNCTION_LIST)
    @ResponseBody
    @Action(description = "查看历程批量审批定义设置分页列表", detail = "查看历程批量审批定义设置分页列表")
    public ResultData list(HttpServletRequest request) {
        QueryFilter filter = new QueryFilter(request, true);
        // 批量审批设置里选择流程没有租户限制,这里也去掉租户限制
        // String tenantId = ContextUtil.getCurrentUserTenantId();
        // filter.addFilter("tenantId", tenantId);

        try{
            List<BpmBatchApproval> batchApprovalList = bpmBatchApprovalService.queryList(filter);
            return getResultDataSuccess("query.success",filter.getPageBean().getTotalCount(), batchApprovalList);
        }catch (Exception e){
            return getResultDataSuccess("query.failure");
        }
    }

    /**
     * 删除流程批量审批定义设置
     * @param request http请求
     * @return 删除结果集合
     */
    @RequestMapping("/delete")
    @Action(description = "删除流程批量审批定义设置",
            execOrder = ActionExecOrder.BEFORE,
            detail = "删除流程批量审批定义设置")
    @ResponseBody
    public ResultData delete(HttpServletRequest request) {
        try {
            String id = RequestUtil.getString(request, "id");
            bpmBatchApprovalService.delById(id);
            return getResultDataSuccess("delete.success");
        } catch (Exception e) {
            e.printStackTrace();
            return getResultDataError("delete.failure");
        }
    }

    /**
     * 查看流程批量批量审批定义设置明细
     * @param request http请求
     * @return 查看明细结果集合
     */
    @RequestMapping("/detail")
    @Action(description = "查看流程批量批量审批定义设置明细", detail = "查看流程批量批量审批定义设置明细")
    @ResponseBody
    public ResultData detail(HttpServletRequest request) {
        String id = RequestUtil.getString(request, "id");
        BpmBatchApproval bpmBatchApproval = bpmBatchApprovalService.getOneById(id);
        if (BeanUtils.isEmpty(bpmBatchApproval)) {
            return getResultDataError("operation.failure");
        }
        return getResultDataSuccess("operation.success", bpmBatchApproval);
    }

    /**
     * 流程批量审批任务列表数据
     * @param request http请求
     * @return 批量审批任务列表页面
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/listBatchTasks")
    @Action(description = "流程批量审批任务列表数据",
            ownermodel = SysAuditModelType.PROCESS_CENTER,
            detail = "流程批量审批任务列表数据")
    public String listBatchTasks(HttpServletRequest request, Model model) {
        String batchId = RequestUtil.getString(request, "batchId");
        BpmBatchApproval batchApproval = bpmBatchApprovalService.getOneById(batchId);
        List<CaseInsensitiveMap> dataList = new ArrayList<>();
        List<String> fieldList = new ArrayList<>();
        List<String> fieldNameList = new ArrayList<>();
        boolean isDataError = false;
        try {
            if (BeanUtils.isNotEmpty(batchApproval)) {
                // 列表显示字段
                fieldList = bpmBatchApprovalService.getFieldList(batchApproval);
                // 列表字段
                fieldNameList = bpmBatchApprovalService.getFieldNameList(batchApproval);
                // 列表数据
                dataList = bpmBatchApprovalService.getDataList(batchApproval, request);
            }
        } catch (Exception e) {
            e.printStackTrace();
            isDataError = true;
        }
        model.addAttribute("dataList", dataList).addAttribute("fieldNameList", fieldNameList)
                .addAttribute("fieldList", fieldList).addAttribute("isDataError", isDataError);
        return getAutoView();
    }

    /**
     * 将流程根据流程定义和节点展示成树数据
     * @param request http请求
     * @return 树形列表页面
     */
    @RequestMapping("/tree")
    @ResponseBody
    @Action(description = "将批量审批任务按照模型定义和节点分类的属性展示",
            ownermodel = SysAuditModelType.PROCESS_CENTER,
            detail = "将批量审批任务按照模型定义和节点分类的属性展示")
    public ResultData tree(HttpServletRequest request) {
        QueryFilter queryFilter = new QueryFilter(request, false);
        // 获取当前用户的可切换角色
        SysRole currentSysRole = SysRoleUtil.getCurrentRole(request);
        if (currentSysRole != null) {
            queryFilter.addFilter("switchRoleId", currentSysRole.getRoleId());
        }

        List<ProcessTask> taskList = bpmService.queryMyTask(queryFilter);
        String tenantId = ContextUtil.getCurrentUserTenantId();
        queryFilter.addFilter("tenantId", tenantId);
        List<BpmBatchApproval> approvalList = bpmBatchApprovalService.queryList(queryFilter);
        Map<String, BpmBatchApproval> map = new LinkedHashMap<>();
        List<BpmTree> treeList = new ArrayList<>();

        if (BeanUtils.isEmpty(taskList) || BeanUtils.isEmpty(approvalList)) {
            return getResultDataError("operation.failure");
        }

        for (BpmBatchApproval approval : approvalList) {
            map.put(approval.getModelKey() + ";" + approval.getNodeId(), approval);
        }

        Map<String, List<ProcessTask>> taskMap = new HashMap<>(16);
        for (ProcessTask task : taskList) {
            if("15".equals(task.getDescription()) || "38".equals(task.getDescription())){
                continue;
            }
            String procDefId = task.getProcessDefinitionId();
            String modelKey = procDefId.split(":")[0];
            String nodeId = task.getTaskDefinitionKey();
            String key = modelKey + ";" + nodeId;
            BpmBatchApproval approval = map.get(key);
            if (BeanUtils.isEmpty(approval)) {
                continue;
            }
            List<ProcessTask> tmpList = taskMap.get(key);
            if (BeanUtils.isEmpty(tmpList)) {
                tmpList = new ArrayList<>();
            }
            tmpList.add(task);
            taskMap.put(key, tmpList);
        }

        // 构建树
        Map<String, BpmBatchApproval> treeMap = new HashMap<>(16);

        // 构建树-节点
        for (Map.Entry<String, BpmBatchApproval> entry : map.entrySet()) {
            String key = entry.getKey();
            BpmBatchApproval bpmBatchApproval = entry.getValue();
            List<ProcessTask> list = taskMap.get(key);
            int count = 0;
            if (BeanUtils.isNotEmpty(list)) {
                count = list.size();
            }
            String modelKey = bpmBatchApproval.getModelKey();
            String nodeId = bpmBatchApproval.getNodeId();
            BpmTree tree = new BpmTree();
            tree.setModelKey(modelKey);
            tree.setNodeId(nodeId);
            tree.setName(bpmBatchApproval.getNodeName() + "(" + count + ")");
            tree.setId(modelKey + "_" + nodeId);
            tree.setPid(modelKey);
            tree.setCount(count);
            tree.setBatchId(bpmBatchApproval.getId());
            treeList.add(tree);

            BpmBatchApproval treeNode = treeMap.get(modelKey);
            if (BeanUtils.isNotEmpty(treeNode)) {
                treeNode.setCount(treeNode.getCount() + count);
                treeMap.put(modelKey, treeNode);
            } else {
                bpmBatchApproval.setCount(count);
                treeMap.put(modelKey, bpmBatchApproval);
            }
        }

        // 构建树-流程定义
        for (Map.Entry<String, BpmBatchApproval> entry : treeMap.entrySet()) {
            BpmBatchApproval bpmBatchApproval = entry.getValue();
            String defKey = bpmBatchApproval.getModelKey();
            String nodeId = bpmBatchApproval.getNodeId();
            int count = bpmBatchApproval.getCount();

            BpmTree tree = new BpmTree();
            tree.setModelKey(defKey);
            tree.setNodeId(nodeId);
            tree.setName(bpmBatchApproval.getSubject() + "(" + count + ")");
            tree.setId(defKey);
            tree.setPid(null);
            tree.setCount(count);
            treeList.add(tree);
        }
        return getResultDataSuccess("operation.success", treeList);
    }

    /**
     * 流程批量审批定义设置字段数据
     * @param request http请求
     * @return 流程批量审批定义设置字段数据
     */
    @RequestMapping("/fieldJsonData")
    @Action(description = "流程批量审批定义设置字段数据", detail = "流程批量审批定义设置字段数据")
    @ResponseBody
    public ResultData fieldJsonData(HttpServletRequest request) {
        String modelKey = RequestUtil.getString(request, "modelKey");
        String nodeId = RequestUtil.getString(request, "nodeId");

        try {
            //获取流程定义
            ActDefModel actDefModel = actDefModelService.getMainByDefKey(modelKey);
            //获取流程某一节点设置
            BpmNodeSet bpmNodeSet = bpmNodeSetService.getByProcDefIdNodeId(actDefModel.getProcDefId(), nodeId);
            Short formType = bpmNodeSet.getFormType();
            if (formType.intValue() == 1) {
                return getResultDataError("urlForm.not.support");
            }
            //根据formKey获取默认发布的表单
            FormDef formDef = formDefService.getDefaultPublishedByFormKey(bpmNodeSet.getFormKey());

            if (BeanUtils.isEmpty(formDef)) {
                //未获取表单字段，提示检查流程是否设置表单
                return getResultDataError("bpmBatchApproval.form.failure");
            }

            //获取字段JSON
            String fieldJson = RequestUtil.getString(request, "fieldJson");
            Map<String, BpmField> fieldMap = getFieldJson(fieldJson);

            String tableId =  formDef.getTableId();
            //通过tableId获取所有字段
            List<FormField> fieldList = formFieldService.queryAllByTableId(tableId);

            List<BpmField> bpmFieldList = new ArrayList<>();
            for (FormField field : fieldList) {
                String fieldName = field.getFieldName();
                BpmField bpmField = fieldMap.get(fieldName);
                if (BeanUtils.isEmpty(bpmField)) {
                    bpmField = new BpmField();
                    bpmField.setFieldDesc(field.getFieldDesc());
                }
                bpmField.setFieldName(fieldName);
                bpmFieldList.add(bpmField);
            }
            formFieldSort(bpmFieldList);

            Map<String, Object> resultMap = new HashMap<>(2);
            resultMap.put("bpmFieldList", bpmFieldList);
            resultMap.put("tableId", tableId);
            return getResultDataSuccess("query.success", resultMap);
        } catch (Exception e) {
            e.printStackTrace();
            return getResultDataError("operation.failure");
        }
    }

    /**
     * 批量审批同意
     * @param request http请求
     * @return 同意结果集合
     */
    @RequestMapping("/batchComplete")
    @ResponseBody
    @Action(description = "批量审批同意",ownermodel = SysAuditModelType.PROCESS_CENTER,detail = "批量审批同意")
    public ResultData batchComplete(HttpServletRequest request) {
        String taskIds = RequestUtil.getString(request, "taskIds");
        String opinion = RequestUtil.getString(request, "opinion");
        try {
            processRunService.nextProcessBatch(taskIds, opinion);
            return getResultDataSuccess("operation.success");
        } catch (Exception e) {
            e.printStackTrace();
            return getResultDataError("operation.failure");
        }
    }


    /**
     * 获取字段json
     * @param fieldJson 字段数据字符串
     * @return 属性集合
     */
    private Map<String, BpmField> getFieldJson(String fieldJson) {
        Map<String, BpmField> map = new HashMap<>(16);
        if (BeanUtils.isEmpty(fieldJson)) {
            return map;
        }
        JSONArray jsonArray = JSONArray.fromObject(fieldJson);
        for (Object obj : jsonArray) {
            BpmField bpmField = new BpmField();
            JSONObject json = (JSONObject) obj;
            String fieldName = (String) json.get("fieldName");
            String fieldDesc = (String) json.get("fieldDesc");
            String isShow = (String) json.get("isShow");
            String sn = (String) json.get("sn");
            bpmField.setFieldName(fieldName);
            bpmField.setFieldDesc(fieldDesc);
            bpmField.setIsShow(Short.parseShort(isShow));
            bpmField.setSn(Integer.parseInt(sn));
            map.put(fieldName, bpmField);
        }
        return map;

    }

    /**
     * 排序 表单属性排序
     * @param list 表单属性集合
     */
    private void formFieldSort(List<BpmField> list) {
        // 排序
        list.sort((preField, sufField) -> {
            int preSn = preField.getSn();
            int sufSn = sufField.getSn();
            return Integer.compare(preSn, sufSn);
        });
    }
}
